/**
  * @brief  Define Peripheral Function
  * @note
  * @param  name, peripheral name
  *         *inst_info, instruction information
  * @retval MemoryMap_t*
  */

#define UART_REG_CR             0x00
#define UART_REG_SR             0x04
#define UART_REG_BAUD           0x08
#define UART_REG_RXD            0x0c
#define UART_REG_TXD            0x10

int _uart(const char *name, InstInfo_t *inst_info)
{
    MemoryMap_t *pm = _find_by_name(name);

    if ( !pm || DATA_MASK(inst_info->mem_addr, 4, 28) != DATA_MASK(pm->address, 4, 28) ) {
        return 0;
    }

    if ( inst_info->mem_we )
    {
        switch ( DATA_MASK(inst_info->mem_addr, 8, 0) )
        {
            case UART_REG_SR  : {
                pm->memory->buf[UART_REG_SR/4] &= ~SHIFT_L(BIT(inst_info->mem_data, 0), 0); // [0]: tx flag
                pm->memory->buf[UART_REG_SR/4] &= ~SHIFT_L(BIT(inst_info->mem_data, 1), 1); // [1]: rx flag
                break;
            }
            case UART_REG_TXD : {
                char ch = (char)pm->memory->buf[UART_REG_TXD/4];
                if ( isprint(ch) || '\r' == ch || '\n' == ch ) {
                    DEBUG_D("%c", ch);
                }
                if ( '\b' == ch ) {
                    DEBUG_D("\b");
                }
                fflush(stdout);
                pm->memory->buf[UART_REG_SR/4] |=  SHIFT_L(1, 0);
                break;
            }
        }
    }

    return 0;
}
